package com.open.capacity.finance.service.impl;

import cn.afterturn.easypoi.excel.ExcelExportUtil;
import cn.afterturn.easypoi.excel.entity.ExportParams;
import com.open.capacity.commons.Result;
import com.open.capacity.finance.dto.AuditModelBaseResult;
import com.open.capacity.finance.entity.AuditModelWarn;
import com.open.capacity.finance.entity.AuditModelWarnPlan;
import com.open.capacity.finance.entity.AuditModelWarnPlanDetail;
import com.open.capacity.finance.service.AbstractAuditMakeResultFactory;
import com.open.capacity.finance.service.AuditModelWarnService;
import com.open.capacity.finance.util.uuid.UUIDUtils;
import com.open.capacity.model.system.LoginAppUser;
import com.open.capacity.model.system.SysUser;
import com.open.capacity.user.model.SysDictData;
import com.open.capacity.user.service.SysDictDataService;
import com.open.capacity.utils.SysUserUtil;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.ss.usermodel.Workbook;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Service;
import com.open.capacity.commons.PageResult;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.open.capacity.commons.CodeEnum;

import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import org.apache.commons.collections4.MapUtils;

import com.open.capacity.finance.entity.AuditModel;
import com.open.capacity.finance.dao.AuditModelDao;
import com.open.capacity.finance.service.AuditModelService;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;

import javax.servlet.http.HttpServletResponse;


@Service
public class AuditModelServiceImpl implements AuditModelService {

    @Autowired
    private ApplicationContext context;

    @Autowired
    private AuditModelWarnService warnService;
    @Autowired
    private AuditModelDao auditModelDao;

    @Autowired
    private SysDictDataService dataService;

    public static final String EXCUTEAUDITCLASSPATHNAME = "com.open.capacity.finance.service.impl.AuditModelActuator%sServiceImpl";


    /**
     * 添加
     *
     * @param auditModel
     */
    public int save(AuditModel auditModel) {
        auditModel.setId(UUIDUtils.getOriginalUUIDWithoutBar());
        auditModel.setStatus(1);
        auditModel.setUpdateTime(new Date());
        return auditModelDao.save(auditModel);
    }

    /**
     * 修改
     *
     * @param auditModel
     */
    public int update(AuditModel auditModel) {
        auditModel.setUpdateTime(new Date());
        return auditModelDao.update(auditModel);
    }

    @Override
    public int updateStatus(String id, Integer status) {
        return auditModelDao.updateStatus(id, status);
    }


    /**
     * 删除
     *
     * @param id
     */
    public int delete(String id) {
        return auditModelDao.delete(id);
    }

    /**
     * 查询记录
     *
     * @param id
     * @return
     */
    public AuditModel findById(String id) {
        AuditModel model = auditModelDao.findById(id);
        if (model != null) {
            model.setCodeAndName(model.getCode() + " " + model.getName());
        }
        return model;
    }

    @Override
    public List<AuditModel> findByIds(String ids) {
        String[] idArray = ids.split(",");
        List<AuditModel> result = new ArrayList<>();
        for (String id : idArray) {
            AuditModel item = findById(id);
            result.add(item);
        }
        return result;
    }

    /**
     * 分页
     *
     * @param params
     * @return
     */
    public PageResult<AuditModel> pageAll(Map<String, Object> params) {
        //设置分页信息，分别是当前页数和每页显示的总记录数【记住：必须在mapper接口中的方法执行之前设置该分页信息】
        if (MapUtils.getInteger(params, "page") != null && MapUtils.getInteger(params, "limit") != null)
            PageHelper.startPage(MapUtils.getInteger(params, "page"), MapUtils.getInteger(params, "limit"), true);

        List<AuditModel> list = auditModelDao.findAll(params);
        list.forEach(t -> {
            t.setCodeAndName(t.getCode() + " " + t.getName());
            t.setCategoryName(dataService.findNameByValue("AUDIT_MODEL_CATEGORYS", t.getCategory()));
        });
        PageInfo<AuditModel> pageInfo = new PageInfo(list);

        return PageResult.<AuditModel>builder().data(pageInfo.getList()).resp_code(CodeEnum.SUCCESS.getCode()).count(pageInfo.getTotal()).build();
    }

    /**
     * 列表
     *
     * @param params
     * @return
     */
    public List<AuditModel> findAll(Map<String, Object> params) {
        List<AuditModel> list = auditModelDao.findAll(params);
        list.forEach(t -> {
            t.setCodeAndName(t.getCode() + " " + t.getName());
        });
        return list;
    }

    @Override
    public void analyseModel(List<String> modelIds, String companyId, Map<String, Object> param) {
        Assert.isTrue(!CollectionUtils.isEmpty(modelIds), "请选择需要执行分析的模型");
        LoginAppUser loginAppUser = SysUserUtil.getLoginAppUser();
        Class<?> clazz;
        AuditModel model;
        AbstractAuditMakeResultFactory bean;
        for (String id : modelIds) {
            model = findById(id);
            if (model.getWarnNeed() != null && (model.getStatus().equals(0) || model.getWarnNeed().equals(0))) {
                continue;
            }
            try {
                clazz = Class.forName(String.format(EXCUTEAUDITCLASSPATHNAME, model.getCode()));
                bean = (AbstractAuditMakeResultFactory) context.getBean(clazz);
            } catch (ClassNotFoundException e) {
                throw new IllegalArgumentException("实例化" + model.getName() + "有误", e);
            } catch (BeansException e) {
                throw new IllegalArgumentException(model.getName() + "未纳入到spring管理", e);
            }
            if (!param.containsKey("companyId") || StringUtils.isEmpty(param.get("companyId").toString())) {
                param.put("companyId", loginAppUser != null ? loginAppUser.getCompanyId() : "00");
            }
            param.put("kjnd", model.getDefaultKjnd());
            bean.run(model, companyId, param);
        }
    }

    @Override
    public void exportExcel(Map<String, Object> param, HttpServletResponse response) {
        LoginAppUser loginAppUser = SysUserUtil.getLoginAppUser();
        String modelId = param.get("modelId").toString();
        String warnId = param.containsKey("warnId") ? param.get("warnId").toString() : null;
        AuditModel model = findById(modelId);

        AuditModelBaseResult reuslt = null;
        Class<?> clazz;
        AbstractAuditMakeResultFactory bean;
        try {
            clazz = Class.forName(String.format(EXCUTEAUDITCLASSPATHNAME, model.getCode()));
            bean = (AbstractAuditMakeResultFactory) context.getBean(clazz);
        } catch (ClassNotFoundException e) {
            throw new IllegalArgumentException("实例化" + model.getName() + "有误", e);
        } catch (BeansException e) {
            throw new IllegalArgumentException(model.getName() + "未纳入到spring管理", e);
        }

        //从本地文件获取结果集
        if (StringUtils.isNotEmpty(warnId)) {
            AuditModelWarn warn = warnService.findById(Long.parseLong(warnId));
            if (warn != null) {
                bean.exportExcelFromJson(modelId, warn.getResultUrl(), response);
            }
        } else {
            if (!param.containsKey("companyId") || StringUtils.isEmpty(param.get("companyId").toString())) {
                param.put("companyId", loginAppUser != null ? loginAppUser.getCompanyId() : "00");
            }
            bean.exportExcel(modelId, param, response);
        }
    }


    @Override
    public AuditModelBaseResult previewResult(Map<String, Object> param) {
        LoginAppUser loginAppUser = SysUserUtil.getLoginAppUser();
        String modelId = param.get("modelId").toString();
        String warnId = param.containsKey("warnId") ? param.get("warnId").toString() : null;
        AuditModel model = findById(modelId);

        AuditModelBaseResult reuslt = null;
        Class<?> clazz;
        AbstractAuditMakeResultFactory bean;
        try {
            clazz = Class.forName(String.format(EXCUTEAUDITCLASSPATHNAME, model.getCode()));
            bean = (AbstractAuditMakeResultFactory) context.getBean(clazz);
        } catch (ClassNotFoundException e) {
            throw new IllegalArgumentException("实例化" + model.getName() + "有误", e);
        } catch (BeansException e) {
            throw new IllegalArgumentException(model.getName() + "未纳入到spring管理", e);
        }

        if (!param.containsKey("companyId") || StringUtils.isEmpty(param.get("companyId").toString())) {
            param.put("companyId", loginAppUser != null ? loginAppUser.getCompanyId() : "00");
        }
        if (!param.containsKey("kjnd") || StringUtils.isEmpty(param.get("kjnd").toString())) {
            param.put("kjnd", model.getDefaultKjnd());
        }
        //从本地文件获取结果集
        if (StringUtils.isNotEmpty(warnId)) {
            AuditModelWarn warn = warnService.findById(Long.parseLong(warnId));
            if (warn != null) {
                reuslt = bean.getDataFromJson(warn.getResultUrl(), param);
            }
        } else {
            reuslt = bean.getData(modelId, param);
        }
        return reuslt;
    }
}
